#pragma once
//============================================================================
// Copyright (C) 2013 Brett R. Jones
//
// Issued to public domain 2013
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================
#include <VxUtilLib/VxDefs.h>
#include <string>
#ifdef WIN_PLATFORM
#include <WinSock2.h>
#include "windows.h"
#else
#include <pthread.h>
#endif // WIN_PLATFORM
#define VX_FLAG_THREAD_ABORT		0x01
#define VX_FLAG_THREAD_RUNNING		0x02
#define VX_FLAG_THREAD_DONE			0x04
#define VX_FLAG_THREAD_CREATED		0x08

typedef void * 	(*VX_THREAD_FUNCTION_T)(void *);
typedef void 	(*VX_THREAD_START_CALLBACK_T)(unsigned int);
typedef void 	(*VX_THREAD_EXIT_CALLBACK_T)(unsigned int, bool);

class VxThread
{
public:
	VxThread(void);
	virtual ~VxThread(void);

	bool IsThreadCreated( void );
	void SetIsThreadCreated( bool bIsCreated);

	bool IsThreadRunning( void );
	void SetIsThreadRunning( bool bIsRunning);

	bool isThreadEndCallbackLocked( void );
	void setIsThreadEndCallbackLocked( bool bIsLocked );

	//! start a thread
	RCODE StartThread(	VX_THREAD_FUNCTION_T 	pfuncThreadFunc,				// function that thread calls
						void * 					pvUserParam,					// user defined param
						const char * 			pThreadName = "WorkerThread",	// thread name
						int 					iExtraStackSpace = 0);			// will be added to minimum stack size

	//! end a thread
	RCODE EndThread(void);

	//! alias for end thread.. i like it better
	RCODE KillThread(void)
	{
		return EndThread();
	}

	//! called  to tell thread to exit
	void 			Abort( bool bAbort );

	//! thread calls this to see if should exit
	bool 			isAborted( void );

	//! get the thread name
	const char * 	GetThreadName( void );

	//! get the user specified parameter
	void * 			GetUserParam( void );

	//! get the thread id
	UINT 			GetThreadId( void );

	//! Thread calls this just before exit
	virtual void 	ThreadAboutToExit( bool bExitThreadNow = true );

	//! set function that will be called when any thread is started
	static void 	SetThreadStartCallback( VX_THREAD_START_CALLBACK_T func );

	//! set function that will be called when any thread is about to exit
	static void 	SetThreadExitCallback( VX_THREAD_EXIT_CALLBACK_T func );

protected:
	//=== vars ===//
	bool								m_bIsExitCallbackLocked;
	void * 								m_pvUserParam; 		// user specified param store here so can be accessed from thread
	unsigned char 						m_u8ThreadFlags;    // thread state flags
	std::string 						m_strThreadName;	// thread user defined name
	static VX_THREAD_START_CALLBACK_T 	m_funcStartCallback;
	static VX_THREAD_EXIT_CALLBACK_T 	m_funcExitCallback;

#ifdef WIN_PLATFORM
	DWORD 								m_uiThreadId;		// thread ID
	HANDLE 								m_hThread;		    // handle to thread
#else
	unsigned int 						m_uiThreadId;		// thread ID
	pthread_t 							m_oThreadInfo;      // pthread info
	pthread_attr_t 						m_oThreadAttr;

#endif
};

//============================================================================
//! get the thread id of current thread that is executing
unsigned int VxGetCurrentThreadId(void);
//============================================================================
